// IndexedDB utility for storing photos
export interface PhotoData {
  id: string
  thumbnail: string
  fullImage: string
  timestamp: number
  taskName?: string
  context?: string
  isCreate?: boolean
  taskCreationId?: string
  studentId?: string
}

class PhotoStorage {
  private dbName = 'HomeworkGradingDB'
  private storeName = 'photos'
  private version = 1
  private db: IDBDatabase | null = null

  async init(): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, this.version)
      
      request.onerror = () => reject(request.error)
      request.onsuccess = () => {
        this.db = request.result
        resolve()
      }
      
      request.onupgradeneeded = (event) => {
        const db = (event.target as IDBOpenDBRequest).result
        if (!db.objectStoreNames.contains(this.storeName)) {
          const store = db.createObjectStore(this.storeName, { keyPath: 'id' })
          store.createIndex('timestamp', 'timestamp', { unique: false })
          store.createIndex('taskName', 'taskName', { unique: false })
        }
      }
    })
  }

  private async ensureDB(): Promise<IDBDatabase> {
    if (!this.db) {
      await this.init()
    }
    if (!this.db) {
      throw new Error('Failed to initialize database')
    }
    return this.db
  }

  async savePhoto(photo: PhotoData): Promise<void> {
    const db = await this.ensureDB()
    return new Promise((resolve, reject) => {
      const transaction = db.transaction([this.storeName], 'readwrite')
      const store = transaction.objectStore(this.storeName)
      const request = store.put(photo)
      
      request.onerror = () => reject(request.error)
      request.onsuccess = () => resolve()
    })
  }

  async savePhotos(photos: PhotoData[]): Promise<void> {
    const db = await this.ensureDB()
    return new Promise((resolve, reject) => {
      const transaction = db.transaction([this.storeName], 'readwrite')
      const store = transaction.objectStore(this.storeName)
      
      let completed = 0
      const total = photos.length
      
      if (total === 0) {
        resolve()
        return
      }
      
      photos.forEach(photo => {
        const request = store.put(photo)
        request.onerror = () => reject(request.error)
        request.onsuccess = () => {
          completed++
          if (completed === total) {
            resolve()
          }
        }
      })
    })
  }

  async getPhotos(): Promise<PhotoData[]> {
    const db = await this.ensureDB()
    return new Promise((resolve, reject) => {
      const transaction = db.transaction([this.storeName], 'readonly')
      const store = transaction.objectStore(this.storeName)
      const request = store.getAll()
      
      request.onerror = () => reject(request.error)
      request.onsuccess = () => resolve(request.result || [])
    })
  }

  async getPhotosByTask(taskName: string): Promise<PhotoData[]> {
    const db = await this.ensureDB()
    return new Promise((resolve, reject) => {
      const transaction = db.transaction([this.storeName], 'readonly')
      const store = transaction.objectStore(this.storeName)
      const index = store.index('taskName')
      const request = index.getAll(taskName)
      
      request.onerror = () => reject(request.error)
      request.onsuccess = () => resolve(request.result || [])
    })
  }

  async deletePhoto(id: string): Promise<void> {
    const db = await this.ensureDB()
    return new Promise((resolve, reject) => {
      const transaction = db.transaction([this.storeName], 'readwrite')
      const store = transaction.objectStore(this.storeName)
      const request = store.delete(id)
      
      request.onerror = () => reject(request.error)
      request.onsuccess = () => resolve()
    })
  }

  async clearPhotos(): Promise<void> {
    const db = await this.ensureDB()
    return new Promise((resolve, reject) => {
      const transaction = db.transaction([this.storeName], 'readwrite')
      const store = transaction.objectStore(this.storeName)
      const request = store.clear()
      
      request.onerror = () => reject(request.error)
      request.onsuccess = () => resolve()
    })
  }

  async getPhotoCount(): Promise<number> {
    const db = await this.ensureDB()
    return new Promise((resolve, reject) => {
      const transaction = db.transaction([this.storeName], 'readonly')
      const store = transaction.objectStore(this.storeName)
      const request = store.count()
      
      request.onerror = () => reject(request.error)
      request.onsuccess = () => resolve(request.result)
    })
  }

  async getPhotosByContext(context: string): Promise<PhotoData[]> {
    const photos = await this.getPhotos()
    return photos.filter(photo => photo.context === context)
  }

  async getTaskCreationPhotos(taskCreationId?: string): Promise<PhotoData[]> {
    const photos = await this.getPhotos()
    return photos.filter(photo => {
      if (taskCreationId) {
        return photo.isCreate === true && photo.taskCreationId === taskCreationId
      }
      return photo.isCreate === true
    })
  }

  async getStudentPhotos(studentId: string): Promise<PhotoData[]> {
    const photos = await this.getPhotos()
    return photos.filter(photo => photo.studentId === studentId && photo.isCreate !== true)
  }

  async getPhotosByTaskAndStudent(taskName: string, studentId: string): Promise<PhotoData[]> {
    const photos = await this.getPhotos()
    return photos.filter(photo => 
      photo.taskName === taskName && 
      photo.studentId === studentId && 
      photo.isCreate !== true
    )
  }

  async deletePhotosByContext(context: string): Promise<void> {
    const photos = await this.getPhotosByContext(context)
    const deletePromises = photos.map(photo => this.deletePhoto(photo.id))
    await Promise.all(deletePromises)
  }

  async deleteTaskCreationPhotos(taskCreationId: string): Promise<void> {
    const photos = await this.getTaskCreationPhotos(taskCreationId)
    const deletePromises = photos.map(photo => this.deletePhoto(photo.id))
    await Promise.all(deletePromises)
  }

  async deleteStudentPhotos(studentId: string): Promise<void> {
    const photos = await this.getStudentPhotos(studentId)
    const deletePromises = photos.map(photo => this.deletePhoto(photo.id))
    await Promise.all(deletePromises)
  }
}

// Export singleton instance
export const photoStorage = new PhotoStorage()